/*
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//双向链表

#ifndef _MC31xx_HAL_LIST_H
#define _MC31xx_HAL_LIST_H

#include "mc31xx_hal.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */

//双向链表结构
typedef struct HAL_DL_LIST {
    struct HAL_DL_LIST *pstPrev; /**< Current node's pointer to the previous node */
    struct HAL_DL_LIST *pstNext; /**< Current node's pointer to the next node */
} HAL_DL_LIST;

//初始化双向链表
//需传入合法指针
static __inline void HAL_ListInit(HAL_DL_LIST *list)
{
    list->pstNext = list;
    list->pstPrev = list;
}

//指向双向链表的下个节点
#define HAL_DL_LIST_FIRST(object) ((object)->pstNext)

//在list节点之后添加node节点
//需传入合法指针
static __inline void HAL_ListAdd(HAL_DL_LIST *list, HAL_DL_LIST *node)
{
    node->pstNext = list->pstNext;
    node->pstPrev = list;
    list->pstNext->pstPrev = node;
    list->pstNext = node;
}

//在双向链表的尾部添加新节点
static __inline void HAL_ListTailInsert(HAL_DL_LIST *list, HAL_DL_LIST *node)
{
    HAL_ListAdd(list->pstPrev, node);
}

//在双向链表头部添加新节点
static __inline void HAL_ListHeadInsert(HAL_DL_LIST *list, HAL_DL_LIST *node)
{
    HAL_ListAdd(list, node);
}

//删除node节点
static __inline void HAL_ListDelete(HAL_DL_LIST *node)
{
    node->pstNext->pstPrev = node->pstPrev;
    node->pstPrev->pstNext = node->pstNext;
    node->pstNext = (HAL_DL_LIST *)NULL;
    node->pstPrev = (HAL_DL_LIST *)NULL;
}

//检查双向链表是否为空
static __inline unsigned char HAL_ListEmpty(HAL_DL_LIST *node)
{
    return (unsigned char)(node->pstNext == node);
}

//获取结构体成员的偏移量
//type:结构名称
//member:成员名称
#define HAL_OFF_SET_OF(type, member) ((u32)&(((type *)0)->member))

//通过成员名称和成员地址获取结构体地址（通过链表节点获取其所在结构体地址）
//item:成员地址（链表节点）
//type:结构名称
//member:成员名称
#define HAL_DL_LIST_ENTRY(item, type, member) \
    ((type *)(void *)((char *)(item) - HAL_OFF_SET_OF(type, member))) \

//迭代指定类型的双向链表所在结构
//item[IN]指针，指向包含要遍历的双链表的结构
//list[IN]指向要遍历的双向链表的指针
//type[IN]结构名称
//member[IN]结构中双链接列表的成员名称
#define HAL_DL_LIST_FOR_EACH_ENTRY(item, list, type, member) \
    for ((item) = HAL_DL_LIST_ENTRY((list)->pstNext, type, member); \
            &(item)->member != (list); \
            (item) = HAL_DL_LIST_ENTRY((item)->member.pstNext, type, member))

//安全的迭代指定双向链表所在结构
#define HAL_DL_LIST_FOR_EACH_ENTRY_SAFE(item, next, list, type, member) \
    for ((item) = HAL_DL_LIST_ENTRY((list)->pstNext, type, member), \
            (next) = HAL_DL_LIST_ENTRY((item)->member.pstNext, type, member); \
            &((item)->member) != (list); \
            (item) = (next), (next) = HAL_DL_LIST_ENTRY((next)->member.pstNext, type, member))

//将list节点从当前链表中删除并重新初始化
static __inline void HAL_ListDelInit(HAL_DL_LIST *list)
{
    list->pstNext->pstPrev = list->pstPrev;
    list->pstPrev->pstNext = list->pstNext;
    HAL_ListInit(list);
}

//迭代双向链表
#define HAL_DL_LIST_FOR_EACH(item, list)    \
     for ((item) = (list)->pstNext; (item) != (list); (item) = (item)->pstNext)

//安全的迭代双向链表
#define HAL_DL_LIST_FOR_EACH_SAFE(item, next, list) \
    for ((item) = (list)->pstNext, (next) = (item)->pstNext; (item) != (list); \
            (item) = (next), (next) = (item)->pstNext)

//定义双向链表并初始化
#define HAL_DL_LIST_HEAD(list) \
    HAL_DL_LIST list = { &(list), &(list) }

/************************************   新增   ************************************/

//获取链表成员数量(不算链表头)
static __inline unsigned int HAL_ListGetLength(HAL_DL_LIST* list)
{
    HAL_DL_LIST *i,*j;
    unsigned int length = 0;
    HAL_DL_LIST_FOR_EACH_SAFE(i,j, list) {
        length++;
    }
    return (unsigned int)length;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

#endif 
